import base64
import json
import pickle

from django import http
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utils import constants
from meiduo_mall.utils.response_code import RET


class CartsView(View):
    # 加入购物车 ajax
    def post(self, request):
        # 获取参数
        data_dcit = json.loads(request.body.decode())
        sku_id = data_dcit.get('sku_id')
        count = data_dcit.get('count')

        # 数据校验
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"})

        # 判断商品是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': "该商品不存在"})

        try:
            # 检测数量数据类型
            count = int(count)
        except Exception as e:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "参数有误"})

        # 库存是否足够
        if count > sku.stock:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "库存不足"})


        if request.user.is_authenticated:
            # 登录用户 数据存入redis
            redis_conn = get_redis_connection('carts')
            # 设置用户购物车数据  用户id、商品id、购买数量
            redis_conn.hincrby("carts_%s" % request.user.id, sku_id, count)
            sku_count = redis_conn.hget("carts_%s" % request.user.id, sku_id)
            if int(sku_count) >5:
                # 设置用户最大购买件数
                redis_conn.hset("carts_%s" % request.user.id, sku_id, constants.SKU_MAX_COUNT)
            # 当用户点击加入购物车 商品默认是选中状态   用户id、商品id
            redis_conn.sadd("selected_%s" % request.user.id, sku_id)
            # 返回响应
            return http.JsonResponse({"code": RET.OK})
        else:
            # 未登录用户，先获取coolie里面的数据
            cookie_cart = request.COOKIES.get("carts")
            cookie_cart_cart = {}
            if cookie_cart:  # 如果之前操作购物车则有数据
                # encode 得到的是6位的byte类型
                cookie_cart_cart = pickle.loads(base64.b64decode(cookie_cart.encode()))
            if sku_id in cookie_cart_cart:
                old_count = cookie_cart_cart[sku_id]['count']
                count += old_count
                if old_count + count > 5:
                    # 设置用户最大购买件数
                    count = constants.SKU_MAX_COUNT
            cookie_cart_cart[sku_id] = {
                'count': count,
                'selected': True
            }
            response = http.JsonResponse({"code": RET.OK})
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_cart)).decode()
            response.set_cookie("carts", cookie_cart)
            return response
            # Create your views here.

    # 渲染购物界面
    def get(self, request):
        user = request.user
        if user.is_authenticated:
            # 如果用户登录，查询redis数据库的购物车数据
            redis_conn = get_redis_connection('carts')
            cart_dict = redis_conn.hgetall('carts_%s' % user.id)  # hgetall 返回键内所有成员
            sku_ids = redis_conn.smembers('selected_%s' % user.id)  # smembers范围键内的所有成员
            sku_list = []
            for sku_id, count in cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "price": str(sku.price),
                    "count": int(count),
                    "amount": str(int(count) * sku.price),
                    "selected": str(sku_id in sku_ids)

                }
                sku_list.append(sku_dict)
            return render(request, 'cart.html', context={'cart_skus': sku_list})
        else:
            cookie_catrs = request.COOKIES.get('carts')
            cookie_dict = {}
            if cookie_catrs:
                cookie_catrs_dict = pickle.loads(base64.b64decode((cookie_catrs.encode())))
                sku_list = []
                for sku_id, selected_count in cookie_catrs_dict.items():
                    sku = SKU.objects.get(id=sku_id)
                    sku_dict = {
                        "id": sku.id,
                        "default_image_url": sku.default_image_url.url,
                        "name": sku.name,
                        "price": str(sku.price),
                        "count": int(selected_count["count"]),
                        "amount": str(selected_count["count"] * sku.price),
                        "selected": str(selected_count["selected"])
                    }
                    sku_list.append(sku_dict)
                cookie_dict = {
                    "cart_skus": sku_list
                }
            # 2,3 返回响应
            return render(request, 'cart.html', context=cookie_dict)

    # 修改商品数量 和选中状态  ajax
    def put(self, request):
        # 获取参数
        data_dict = json.loads(request.body.decode())
        sku_id = data_dict.get("sku_id")
        count = data_dict.get("count")
        selected = data_dict.get("selected")

        # 校验参数
        # 为空校验
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"})
        try:
            count = int(count)
        except Exception as e:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "状态有误"})

        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.DBERR, "errmsg": "商品不存在"})

        if count > sku.stock:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "库存不足"})

        if request.user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_conn.hset("carts_%s" % request.user.id, sku_id, count)
            if selected:
                redis_conn.sadd("selected_%s" % request.user.id, sku_id)
            else:
                redis_conn.srem("selected_%s" % request.user.id, sku_id)

            cart_sku = {
                "id": sku.id,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": int(count),
                "amount": str(int(count) * sku.price),
                "selected": str(selected)
            }
            # 判断count是否整数
            return http.JsonResponse({"code": RET.OK, "cart_sku": cart_sku})
        else:
            # 4,1 获取cookie数据
            cookie_cart = request.COOKIES.get("carts")

            # 4,2 字符串转字典
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 4,3 数据修改
            cookie_cart_dict[sku_id] = {
                "count": count,
                "selected": selected
            }

            # 4,4 拼接数据返回响应
            cart_sku = {
                "id": sku.id,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": int(count),
                "amount": str(int(count) * sku.price),
                "selected": selected
            }
            response = http.JsonResponse({"code": RET.OK, "cart_sku": cart_sku})
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("carts", cookie_cart)
            return response

    # 删除商品  ajax
    def delete(self, request):
        data_dict = json.loads(request.body.decode())
        sku_id = data_dict.get("sku_id")

        if not sku_id:
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"})

        if request.user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_conn.hdel("carts_%s" % request.user.id, sku_id)
            redis_conn.srem("selected_%s" % request.user.id, sku_id)
            return http.JsonResponse({"code": RET.OK})
        else:
            cookie_catrs = request.COOKIES.get('carts')

            cookie_catrs_dict = {}
            if cookie_catrs:
                cookie_catrs_dict = pickle.loads(base64.b64decode(cookie_catrs.encode()))
            if sku_id in cookie_catrs_dict:
                del cookie_catrs_dict[sku_id]

            cookie_cart = base64.b64encode(pickle.dumps(cookie_catrs_dict))
            response = http.JsonResponse({"code": RET.OK})
            response.set_cookie("carts", cookie_cart)
            return response


# 判断是否全选状态
class CartsAllSelectedView(View):
    # 购物车全选功能   ajax
    def put(self, request):
        data_dict = json.loads(request.body.decode())
        selected = data_dict.get("selected")
        try:
            selected = bool(selected)
        except Exception as e:
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数有误"})

        if request.user.is_authenticated:
            redis_conn = get_redis_connection("carts")
            sku_ids = redis_conn.hkeys("carts_%s" % request.user.id)
            if selected:
                redis_conn.sadd("selected_%s" % request.user.id, *sku_ids)
            else:
                redis_conn.srem("selected_%s" % request.user.id, *sku_ids)

            return http.JsonResponse({"code": RET.OK})
        else:
            cookie_catrs = request.COOKIES.get('carts')
            cookie_cart_dict = {}
            if cookie_catrs:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_catrs.encode()))
            for sku_id, selected_count in cookie_cart_dict.items():
                selected_count["selected"] = selected
                # 4,4 拼接数据返回响应
            response = http.JsonResponse({"code": RET.OK})
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("carts", cookie_cart)
            return response


# 小购物车
class CartsSimpleView(View):
    def get(self, request):
        if request.user.is_authenticated:
            redis_conn = get_redis_connection("carts")
            cart_dict = redis_conn.hgetall("carts_%s" % request.user.id)

            sku_list = []
            for sku_id, count in cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                # cart_total_count += count
                sku_dict = {
                    "name": sku.name,
                    "default_image_url": sku.default_image_url.url,
                    "id": sku.id,
                    "count": int(count),
                }
                sku_list.append(sku_dict)
            return http.JsonResponse({"cart_skus": sku_list})

        else:
            cookie_catrs = request.COOKIES.get('carts')
            sku_list = []
            if cookie_catrs:
                cookie_catrs_dict = pickle.loads(base64.b64decode((cookie_catrs.encode())))
                cookie_dict = {}
                for sku_id, selected_count in cookie_catrs_dict.items():
                    sku = SKU.objects.get(id=sku_id)
                    sku_dict = {
                        "id": sku.id,
                        "default_image_url": sku.default_image_url.url,
                        "name": sku.name,
                        "price": str(sku.price),
                        "count": int(selected_count["count"]),
                        "amount": str(selected_count["count"] * sku.price),
                        "selected": str(selected_count["selected"])
                    }
                    sku_list.append(sku_dict)

                    # 2,3 返回响应
            return http.JsonResponse({"cart_skus": sku_list})
